package top.hudk.tank.factory;


import top.hudk.tank.config.GameConfig;
import top.hudk.tank.config.ResourceMgr;
import top.hudk.tank.constant.GameConstant;
import top.hudk.tank.enums.Dir;
import top.hudk.tank.enums.Group;
import top.hudk.tank.frame.AbstractGameFrame;
import top.hudk.tank.model.GameApplicationContext;
import top.hudk.tank.model.GameObject;
import top.hudk.tank.strategy.FireStrategy;
import top.hudk.tank.strategy.SingleShotFireStrategy;
import top.hudk.tank.utils.Audio;
import top.hudk.tank.utils.DirUtil;
import top.hudk.tank.utils.RandomUtil;
import top.hudk.tank.utils.ThreadPoolUtils;

import java.awt.*;

/**
 * 作用：
 *
 * @author hudk
 * @date 2020/9/10 7:45
 */
public abstract class Tank extends GameObject {
    public Tank() {
    }

    /**
     * 设置坦克的位置
     * @param x
     * @param y
     */
    public void setPlace(int x, int y){
        super.setPlace(x, y);
        this.oldX = x;
        this.oldY = y;
    }

    private int oldX;

    private int oldY;

    /**
     * 坦克朝向的方向
     */
    private Dir dir = DirUtil.randomDir();
    /**
     * 敌我阵营属性
     */
    private Group group;
    /**
     * 坦克是否在移动
     */
    private boolean moving = false;

    /**
     * 是否允许覆盖显示,默认不允许
     */
    private boolean allowCover = false;

    /**
     * 是否出动，没有出动的坦克，不会被显示出来
     */
    private boolean go = false;



    private int lifeValue = 100;



    /**
     * 坦克是否存活
     */
    private boolean living = true;
    /**
     * 坦克移动速度
     */
    private int speed = GameConfig.BAD_TANK_SPEED;
    /**
     * 开火概率
     */
    private double fireProbability = RandomUtil.getProbability(GameConfig.FIRE_POWER);

    /**
     * 改变方向概率
     */
    private double dirProbability = RandomUtil.getProbability(GameConfig.CHANGE_DIRECTION);

    /**
     * 渲染坦克位置和方向
     *
     * @param g
     */
    @Override
    public void paint(Graphics g, AbstractGameFrame gameFrame) {
        //存活检测
        if (!isLiving()) {
            //爆炸效果
            this.explode();
            return;
        }
        //绘制位置和外观
        this.draw(g);
        //移动
        this.move(gameFrame);
        //随机行为, 默认敌方坦克会随机走动和随机开火
        this.randomBehaviour();
    }


    /**
     * 触发自爆
     */
    public void explode() {
        GameApplicationContext.getInstance().remove(this);
        Explode explode = DefaultFactory.getInstance().createExplode();
        int x = getX() + getWidth() / 2 - explode.getWidth() / 2;
        int y = getY() + getHeight() / 2 - explode.getHeight() / 2;
        explode.init(x, y);
        GameApplicationContext.getInstance().add(explode);
        ThreadPoolUtils.execute(()->new Audio(GameConstant.FIRE_MUSIC_FILE_PATH).play());
    }

    /**
     * 绘制位置和外观
     *
     * @param g
     */
    public void draw(Graphics g) {
//        if(!go){
//            return;
//        }
//        g.drawRect(getX(), getY(), getWidth(), getHeight());
//        g.setColor(Color.GREEN);
        switch (getDir()) {
            case LEFT:
                g.drawImage(getGroup() == Group.GOOD ? ResourceMgr.goodTankL : ResourceMgr.badTankL, getX(), getY(), null);
                break;
            case UP:
                g.drawImage(getGroup() == Group.GOOD ? ResourceMgr.goodTankU : ResourceMgr.badTankU, getX(), getY(), null);
                break;
            case RIGHT:
                g.drawImage(getGroup() == Group.GOOD ? ResourceMgr.goodTankR : ResourceMgr.badTankR, getX(), getY(), null);
                break;
            case DOWN:
                g.drawImage(getGroup() == Group.GOOD ? ResourceMgr.goodTankD : ResourceMgr.badTankD, getX(), getY(), null);
                break;
            default:
                break;
        }
    }

    /**
     * 随机行为
     */
    public void randomBehaviour() {
        //默认敌方坦克会随机走动和随机开火
        if (Group.BAD.equals(getGroup())) {
            randomFire();
            turnDir(GameConfig.BAD_TANK_CHANGE_DIRECTION_BY_SECOND);
        }
    }

    private void turnDir(int secondNumb){
        setDir(DirUtil.randomLeftOrRightDir(getDir(),
                RandomUtil.returnTrueAfterSeconds(secondNumb)));
    }


    /**
     * 坦克移动
     */
    public void move(AbstractGameFrame gameFrame) {

        if (!moving) {
            return;
        }
        oldX = x;
        oldY = y;
        switch (dir) {
            case LEFT:
                x -= speed;
                break;
            case UP:
                y -= speed;
                break;
            case RIGHT:
                x += speed;
                break;
            case DOWN:
                y += speed;
                break;
            default:
                break;
        }
        boundsCheck(gameFrame);
        rect.x = this.x;
        rect.y = this.y;
    }

    /**
     * 位置回退，一般用于撞到物体后执行
     */
    public void back(){
        x = oldX;
        y = oldY;
        //随机向左或者向右转向
        if(Group.BAD.equals(group)){
            turnDir(1);
        }
    }

    /**
     * 按照一定概率随机开火
     */
    public void randomFire() {
        if (RandomUtil.randomBoolean(fireProbability)) {
            fire(SingleShotFireStrategy.getInstance());
        }
    }

    /**
     * 窗口边缘检测，坦克不允许开出显示范围之外
     */
    public void boundsCheck(AbstractGameFrame gameFrame) {
        boolean boundary = false;
        if (x >= gameFrame.maxX(this)) {
            x = gameFrame.maxX(this);
            boundary = true;
        }
        if (x <= gameFrame.minX()) {
            x = gameFrame.minX();
            boundary = true;
        }
        if (y >= gameFrame.maxY(this)) {
            y = gameFrame.maxY(this);
            boundary = true;
        }
        if (y <= gameFrame.minY()) {
            y = gameFrame.minY();
            boundary = true;
        }
        if (boundary && Group.BAD.equals(this.group)){
            //坦克位于界面边缘时，增大其改变方向的概率
            turnDir(1);
        }
    }

    /**
     * 坦克开火
     */
    public void fire(FireStrategy fireStrategy) {
        if(isLiving()){
            fireStrategy.fire(this);
        }
    }

    public int getLifeValue() {
        return lifeValue;
    }

    public void setLifeValue(int lifeValue) {
        this.lifeValue = lifeValue;
    }

    public double getFireProbability() {
        return fireProbability;
    }

    public void setFireProbability(int fireProbability) {
        this.fireProbability = fireProbability;
    }

    public double getDirProbability() {
        return dirProbability;
    }

    public void setDirProbability(int dirProbability) {
        this.dirProbability = dirProbability;
    }

    /**
     * 坦克死亡
     */
    public void hit() {
        if(lifeValue <= 0){
            living = false;
            return;
        }
        lifeValue -= 20;
    }


    public Group getGroup() {
        return group;
    }

    public void setGroup(Group group) {
        this.group = group;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
         this.speed = speed;
    }

    public boolean isMoving() {
        return moving;
    }

    public void setMoving(boolean moving) {
        this.moving = moving;
    }

    public boolean isLiving() {
        return living;
    }

    public void setLiving(boolean living) {
        this.living = living;
    }


    public Dir getDir() {
        return dir;
    }

    public void setDir(Dir dir) {
        this.dir = dir;
    }


    public int getOldX() {
        return oldX;
    }

    public void setOldX(int oldX) {
        this.oldX = oldX;
    }

    public int getOldY() {
        return oldY;
    }

    public void setOldY(int oldY) {
        this.oldY = oldY;
    }

    public boolean isAllowCover() {
        return allowCover;
    }

    public void setAllowCover(boolean allowCover) {
        this.allowCover = allowCover;
    }

    public boolean isGo() {
        return go;
    }

    public void setGo(boolean go) {
        this.go = go;
    }
}
